package kn.pulldata.task;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.thread.ThreadUtil;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import cn.hutool.http.HttpUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import kn.pulldata.common.RedisKey;
import kn.pulldata.req.MatchByDirectionReq;
import kn.pulldata.req.MatchByKeywordReq;
import kn.pulldata.resp.PlanResp;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.geo.Point;
import org.springframework.data.redis.core.RedisCallback;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import java.util.List;
import java.util.Objects;
import java.util.Set;

/**
 * 拉取关键字匹配方案列表
 */
@Component
@Slf4j
public class PullDataTask {

    @Value("${monitor.keyword.url}")
    private String getKeywordUrl;
    @Value("${monitor.direction.url}")
    private String getDirectionUrl;
    @Value("${monitor.getMonitorLoca.url}")
    private String getMonitorLocaUrl;

    @Value("${monitor.getPoleMonitorLoca.url}")
    private String getPoleMonitorLocaUrl;

    @Autowired
    @Qualifier("redisTemplateWithString")
    private RedisTemplate<String,String> redisTemplate;

    @Scheduled(fixedRate = 60000) // 每隔60秒拉取数据
    public void PullData(){
        // 拉取邯郸 和 小极方案
        ThreadUtil.execAsync(this::GetPoleMonitorLocal);
        // 拉取定向方案
        ThreadUtil.execAsync(this::PullDirectionData);
        // 拉取关键字方案
        ThreadUtil.execAsync(this::PullKeywordData);
    }

    public void PullKeywordData(){
        // 请求接口
        log.info("PullDataTask.PullKeywordData开始执行");
        HttpRequest httpRequest = HttpUtil.createGet(getKeywordUrl + 0,true);
        HttpResponse httpResponse = httpRequest.execute();


        KeywordToRedis(httpResponse, RedisKey.MONITOR_KEYWORD_REDIS_KEY, "PullKeywordData数据已保存到Redis");


        log.info("PullDataTask.PullKeywordData结束");

    }
    private void KeywordToRedis(HttpResponse httpResponse, String redisKey, String msg) {
        if (httpResponse != null && httpResponse.body() != null) {
            // 解析 JSON 并直接转换为 MatchByDirectionReq 对象列表
            String body = httpResponse.body();
            JSONObject jsonObject = JSONUtil.parseObj(body);
            List<MatchByKeywordReq> keywordReqList = JSONUtil.parseArray(jsonObject.getStr("data")).toList(MatchByKeywordReq.class);
            try {
                if(!keywordReqList.isEmpty()){
                    Set<Object> existingKeys = redisTemplate.opsForHash().keys(redisKey);
                    if(CollUtil.isNotEmpty(existingKeys)){
                        Long delete = redisTemplate.opsForHash().delete(redisKey, existingKeys.toArray());
                        log.info("关键字方案删除成功：{}",delete);

                    }
                    redisTemplate.executePipelined((RedisCallback<Object>) connection -> {
                        for (MatchByKeywordReq keywordReq : keywordReqList) {
                            // 使用HASH存储 PlanResp 对象，以 PlanID 为 key
                            connection.hSet(
                                    Objects.requireNonNull(redisTemplate.getStringSerializer().serialize(redisKey)),
                                    Objects.requireNonNull(redisTemplate.getStringSerializer().serialize(String.valueOf(keywordReq.getPlanID()))),
                                    Objects.requireNonNull(redisTemplate.getStringSerializer().serialize(JSONUtil.toJsonStr(keywordReq)))
                            );
                        }
                        return null;
                    });
                }
            } catch (Exception e) {
                e.printStackTrace();
            }

            log.info(msg);
        }
    }
    public void PullDirectionData(){

        // 请求接口
        log.info("PullDataTask.PullDirectionData开始执行");
        HttpRequest httpRequest = HttpUtil.createGet(getDirectionUrl + 0,true);
        HttpResponse httpResponse = httpRequest.execute();


        directionToRedis(httpResponse, RedisKey.MONITOR_DIRECTION_REDIS_KEY, "DirectionData数据已保存到Redis");


        log.info("PullDataTask.PullDirectionData结束");

    }

    private void directionToRedis(HttpResponse httpResponse, String redisKey, String msg) {
        if (httpResponse != null && httpResponse.body() != null) {
            // 解析 JSON 并直接转换为 MatchByDirectionReq 对象列表
            String body = httpResponse.body();
            JSONObject jsonObject = JSONUtil.parseObj(body);
            List<MatchByDirectionReq> directionReqList = JSONUtil.parseArray(jsonObject.getStr("data")).toList(MatchByDirectionReq.class);
            try {
                if (!directionReqList.isEmpty()){
                    Set<Object> existingKeys = redisTemplate.opsForHash().keys(redisKey);
                    if(CollUtil.isNotEmpty(existingKeys)){
                        Long delete = redisTemplate.opsForHash().delete(redisKey, existingKeys.toArray());
                        log.info("定向方案删除成功：{}",delete);
                    }

                    redisTemplate.executePipelined((RedisCallback<Object>) connection -> {
                        for (MatchByDirectionReq directionReq : directionReqList) {
                            // 使用HASH存储 PlanResp 对象，以 PlanID 为 key
                            connection.hSet(
                                    Objects.requireNonNull(redisTemplate.getStringSerializer().serialize(redisKey)),
                                    Objects.requireNonNull(redisTemplate.getStringSerializer().serialize(String.valueOf(directionReq.getPlanID()))),
                                    Objects.requireNonNull(redisTemplate.getStringSerializer().serialize(JSONUtil.toJsonStr(directionReq)))
                            );

                        }
                        return null;
                    });
                    log.info(msg);
                }
                }catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    public void GetPoleMonitorLocal(){

        // 请求接口
        log.info("PullDataTask.GetPoleMonitorLocal开始执行");
        HttpRequest httpRequest = HttpUtil.createGet(getMonitorLocaUrl,true);
        HttpResponse httpResponse = httpRequest.execute();


        extracted(httpResponse, RedisKey.MONITOR_LOCAL_REDIS_KEY, "MonitorLoca数据已保存到Redis");
        httpRequest = httpRequest.setUrl(getPoleMonitorLocaUrl + 0);
        httpResponse = httpRequest.execute();
        extracted(httpResponse, RedisKey.POLE_MONITOR_LOCAL_REDIS_KEY, "PoleMonitorLoca数据已保存到Redis");
        log.info("PullDataTask.GetPoleMonitorLocal结束");

    }

    private void extracted(HttpResponse httpResponse, String redisKey, String msg) {
        if (httpResponse != null && httpResponse.body() != null) {
            // 解析 JSON 并直接转换为 PlanResp 对象列表
            String body = httpResponse.body();
            JSONObject jsonObject = JSONUtil.parseObj(body);
            List<PlanResp> planRespList = JSONUtil.parseArray(jsonObject.getStr("data")).toList(PlanResp.class);

            if(!planRespList.isEmpty()){

                Set<Object> existingKeysHash = redisTemplate.opsForHash().keys(redisKey +":hash");
                if(CollUtil.isNotEmpty(existingKeysHash)){
                    Boolean delete = redisTemplate.delete(redisKey + ":GPS");
                    log.info("小极方案删除成功：{}",delete);
                    Long delete1 = redisTemplate.opsForHash().delete(redisKey + ":hash", existingKeysHash.toArray());
                    log.info("小极位置方案删除成功：{}",delete1);
                }

                redisTemplate.executePipelined((RedisCallback<Object>) connection -> {
                    for (PlanResp planResp : planRespList) {
                        // 使用GEOADD将PlanResp的经纬度添加到Redis
                        if(Objects.nonNull(planResp.getLongitude()) && Objects.nonNull(planResp.getLatitude())){
                            connection.geoAdd(
                                    Objects.requireNonNull(redisTemplate.getStringSerializer().serialize(redisKey + ":GPS")),  // 序列化 key
                                    new Point(planResp.getLongitude(), planResp.getLatitude()),               // 使用 Point 对象传递经纬度
                                    Objects.requireNonNull(redisTemplate.getStringSerializer().serialize(String.valueOf(planResp.getPlanID()))) // 序列化 member
                            );
                            // 使用HASH存储 PlanResp 对象，以 PlanID 为 key
                            connection.hSet(
                                    Objects.requireNonNull(redisTemplate.getStringSerializer().serialize(redisKey + ":hash")),
                                    Objects.requireNonNull(redisTemplate.getStringSerializer().serialize(String.valueOf(planResp.getPlanID()))),
                                    Objects.requireNonNull(redisTemplate.getStringSerializer().serialize(JSONUtil.toJsonStr(planResp)))  // 序列化 PlanResp 对象
                            );
                        }

                    }
                    return null;
                });
                log.info(msg);
            }
        }
    }

}
